generative art python

54

import math
import random

import numpy as np

from PyQt5.QtGui import QColor, QPen
from PyQt5.QtCore import QPointF

import painter
from utils import QColor_HSV, save, Perlin2D

def draw(width, height, color=200, backgroundColor=(0,0,0), perlinFactorW=2, perlinFactorH=2, step=0.001):
    seed = random.randint(0, 100000000)

    # Set the random seed for repeatability
    np.random.seed(seed)

    p = painter.Painter(width, height)

    # Allow smooth drawing
    p.setRenderHint(p.Antialiasing)

    # Draw the background color
    p.fillRect(0, 0, width, height, QColor( *backgroundColor ))

    # Set the pen color
    p.setPen(QPen(QColor(150, 150, 225, 5), 2))
    
    print('Creating Noise...')
    p_noise = Perlin2D(width, height, perlinFactorW, perlinFactorH)
    print('Noise Generated!')

    MAX_LENGTH = 2 * width
    STEP_SIZE = step * max(width, height)
    NUM = int(width * height / 1000)
    POINTS = [(random.randint(0, width - 1), random.randint(0, height - 1)) for i in range(NUM)]

    for k, (x_s, y_s) in enumerate(POINTS):
        print(f'{100 * (k + 1) / len(POINTS):.1f}'.rjust(5) + '% Complete', end='\r')

        # The current line length tracking variable
        c_len = 0

        # Actually draw the flow field
        while c_len < MAX_LENGTH:
            # Set the pen color for this segment
            sat = 200 * (MAX_LENGTH - c_len) / MAX_LENGTH
            hue = (color + 130 * (height - y_s) / height) % 360
            p.setPen(QPen(QColor_HSV(hue, sat, 255, 20), 2))

            # angle between -pi and pi
            angle = p_noise[int(x_s), int(y_s)] * math.pi

            # Compute the new point
            x_f = x_s + STEP_SIZE * math.cos(angle)
            y_f = y_s + STEP_SIZE * math.sin(angle)

            # Draw the line
            p.drawLine(QPointF(x_s, y_s), QPointF(x_f, y_f))

            # Update the line length
            c_len += math.sqrt((x_f - x_s) ** 2 + (y_f - y_s) ** 2)

            # Break from the loop if the new point is outside our image bounds
            # or if we've exceeded the line length; otherwise update the point
            if x_f < 0 or x_f >= width or y_f < 0 or y_f >= height or c_len > MAX_LENGTH:
                break
            else:
                x_s, y_s = x_f, y_f

    save(p, fname=f'image_{seed}', folder='.', overwrite=True)

draw(3000, 2000, color=63, perlinFactorW=4, perlinFactorH=5, step=0.35)

Comments

Submit
0 Comments